//! 消息队列
//!
//! 基于 crossbeam-channel 实现的异步消息队列。
//!
//! ## 主要类型
//!
//! - [`LogChannel`] - 日志消息通道
//! - [`DEFAULT_QUEUE_SIZE`] - 默认队列大小常量
//!
//! ## 示例
//!
//! ```rust
//! use log4r::async_rt::{LogChannel, DEFAULT_QUEUE_SIZE};
//!
//! // 使用默认容量创建通道
//! let channel = LogChannel::with_default_capacity();
//! assert_eq!(channel.capacity(), Some(DEFAULT_QUEUE_SIZE));
//!
//! // 使用自定义容量创建通道
//! let channel = LogChannel::new(5000);
//! assert_eq!(channel.capacity(), Some(5000));
//! ```

use std::sync::atomic::{AtomicUsize, Ordering};

use crossbeam_channel::{bounded, Receiver, Sender, TrySendError};

use crate::error::Log4rError;
use crate::event::LogEvent;

/// 默认队列大小
///
/// 根据架构文档，默认队列容量为 10000 条消息。
pub const DEFAULT_QUEUE_SIZE: usize = 10000;

/// 背压警告阈值（每 1000 次输出一次警告）
const BACKPRESSURE_WARNING_THRESHOLD: usize = 1000;

/// 日志消息通道
///
/// 基于 crossbeam-channel 的 bounded channel 实现，
/// 用于在用户线程和后台写入线程之间传递日志事件。
///
/// ## 线程安全
///
/// `LogChannel` 实现了 `Send + Sync`，可以安全地在线程间共享。
/// `Sender` 可以克隆并在多个线程中使用（多生产者）。
///
/// ## 背压策略
///
/// 当队列满时，使用 Block 策略阻塞发送线程直到有空间。
/// 背压事件累计 1000 次时输出 stderr 警告。
///
/// ## 示例
///
/// ```rust
/// use log4r::async_rt::LogChannel;
/// use log4r::{Level, LogEvent};
///
/// let channel = LogChannel::new(100);
///
/// // 发送日志事件
/// let event = LogEvent::new(Level::Info, "test", "Hello");
/// channel.try_send(event).unwrap();
///
/// // 检查队列状态
/// assert_eq!(channel.len(), 1);
/// assert!(!channel.is_empty());
/// ```
pub struct LogChannel {
    /// 发送端
    sender: Sender<LogEvent>,
    /// 接收端
    receiver: Receiver<LogEvent>,
    /// 队列容量
    capacity: usize,
    /// 背压计数器（记录队列满导致阻塞的次数）
    backpressure_count: AtomicUsize,
}

// 编译时断言：验证 LogChannel 实现 Send + Sync
const _: () = {
    const fn assert_send_sync<T: Send + Sync>() {}
    assert_send_sync::<LogChannel>();
};

impl LogChannel {
    /// 创建指定容量的通道
    ///
    /// # Arguments
    ///
    /// * `capacity` - 队列容量
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    ///
    /// let channel = LogChannel::new(5000);
    /// assert_eq!(channel.capacity(), Some(5000));
    /// ```
    pub fn new(capacity: usize) -> Self {
        let (sender, receiver) = bounded(capacity);
        Self {
            sender,
            receiver,
            capacity,
            backpressure_count: AtomicUsize::new(0),
        }
    }

    /// 使用默认容量创建通道
    ///
    /// 默认容量为 [`DEFAULT_QUEUE_SIZE`]（10000）。
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::{LogChannel, DEFAULT_QUEUE_SIZE};
    ///
    /// let channel = LogChannel::with_default_capacity();
    /// assert_eq!(channel.capacity(), Some(DEFAULT_QUEUE_SIZE));
    /// ```
    pub fn with_default_capacity() -> Self {
        Self::new(DEFAULT_QUEUE_SIZE)
    }

    /// 获取发送端克隆
    ///
    /// 返回 `Sender` 的克隆，可以在多个线程中使用。
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    ///
    /// let channel = LogChannel::new(100);
    /// let sender = channel.sender();
    /// // sender 可以移动到其他线程
    /// ```
    pub fn sender(&self) -> Sender<LogEvent> {
        self.sender.clone()
    }

    /// 获取接收端引用
    ///
    /// 返回 `Receiver` 的引用，通常由后台工作线程使用。
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    ///
    /// let channel = LogChannel::new(100);
    /// let receiver = channel.receiver();
    /// ```
    pub fn receiver(&self) -> &Receiver<LogEvent> {
        &self.receiver
    }

    /// 发送日志事件（Block 背压策略）
    ///
    /// 实现 Block 背压策略：
    /// - 先尝试非阻塞发送
    /// - 队列满时递增背压计数器，然后阻塞等待
    /// - 每 1000 次背压输出 stderr 警告
    /// - 阻塞解除后正常发送
    ///
    /// # Arguments
    ///
    /// * `event` - 要发送的日志事件
    ///
    /// # Errors
    ///
    /// 如果接收端已断开，返回 `Log4rError::ChannelError`。
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    /// use log4r::{Level, LogEvent};
    ///
    /// let channel = LogChannel::new(100);
    /// let event = LogEvent::new(Level::Info, "test", "message");
    /// channel.send(event).unwrap();
    /// ```
    pub fn send(&self, event: LogEvent) -> Result<(), Log4rError> {
        // 先尝试非阻塞发送
        match self.sender.try_send(event) {
            Ok(()) => Ok(()),
            Err(TrySendError::Full(event)) => {
                // 队列满，递增背压计数器
                let count = self.backpressure_count.fetch_add(1, Ordering::Relaxed) + 1;

                // 每 1000 次输出警告 (AC-6.4.3)
                if count % BACKPRESSURE_WARNING_THRESHOLD == 0 {
                    eprintln!(
                        "[log4r] 警告: 异步队列背压已发生 {} 次，考虑增加 queue_size 或优化日志输出",
                        count
                    );
                }

                // 阻塞发送 (AC-6.4.1, AC-6.4.2)
                self.sender.send(event).map_err(|e| {
                    Log4rError::ChannelError(format!("发送失败: 接收端已断开 - {}", e))
                })
            }
            Err(TrySendError::Disconnected(_)) => Err(Log4rError::ChannelError(
                "发送失败: 接收端已断开".to_string(),
            )),
        }
    }

    /// 获取背压计数
    ///
    /// 返回队列满导致阻塞的累计次数。
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    ///
    /// let channel = LogChannel::new(100);
    /// assert_eq!(channel.backpressure_count(), 0);
    /// ```
    pub fn backpressure_count(&self) -> usize {
        self.backpressure_count.load(Ordering::Relaxed)
    }

    /// 尝试发送日志事件（非阻塞）
    ///
    /// 如果队列已满或接收端已断开，立即返回错误。
    ///
    /// # Arguments
    ///
    /// * `event` - 要发送的日志事件
    ///
    /// # Errors
    ///
    /// - `TrySendError::Full` - 队列已满
    /// - `TrySendError::Disconnected` - 接收端已断开
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    /// use log4r::{Level, LogEvent};
    ///
    /// let channel = LogChannel::new(100);
    /// let event = LogEvent::new(Level::Info, "test", "message");
    ///
    /// match channel.try_send(event) {
    ///     Ok(()) => println!("发送成功"),
    ///     Err(e) => println!("发送失败: {:?}", e),
    /// }
    /// ```
    pub fn try_send(&self, event: LogEvent) -> Result<(), TrySendError<LogEvent>> {
        self.sender.try_send(event)
    }

    /// 获取当前队列长度
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    ///
    /// let channel = LogChannel::new(100);
    /// assert_eq!(channel.len(), 0);
    /// ```
    pub fn len(&self) -> usize {
        self.sender.len()
    }

    /// 检查队列是否为空
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    ///
    /// let channel = LogChannel::new(100);
    /// assert!(channel.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.sender.is_empty()
    }

    /// 检查队列是否已满
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    ///
    /// let channel = LogChannel::new(100);
    /// assert!(!channel.is_full());
    /// ```
    pub fn is_full(&self) -> bool {
        self.sender.is_full()
    }

    /// 获取队列容量
    ///
    /// # Examples
    ///
    /// ```rust
    /// use log4r::async_rt::LogChannel;
    ///
    /// let channel = LogChannel::new(5000);
    /// assert_eq!(channel.capacity(), Some(5000));
    /// ```
    pub fn capacity(&self) -> Option<usize> {
        Some(self.capacity)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::level::Level;

    // UT-6.1-001: 测试 LogChannel 创建和默认容量
    #[test]
    fn test_logchannel_new_with_capacity() {
        // GIVEN: 指定容量
        let capacity = 5000;

        // WHEN: 创建 LogChannel
        let channel = LogChannel::new(capacity);

        // THEN: 容量应正确设置
        assert_eq!(channel.capacity(), Some(capacity));
        assert!(channel.is_empty());
        assert!(!channel.is_full());
        assert_eq!(channel.len(), 0);
    }

    // UT-6.1-002: 测试默认容量常量
    #[test]
    fn test_default_queue_size_constant() {
        // GIVEN/WHEN: 检查常量值
        // THEN: 默认队列大小应为 10000
        assert_eq!(DEFAULT_QUEUE_SIZE, 10000);
    }

    // UT-6.1-003: 测试 with_default_capacity
    #[test]
    fn test_with_default_capacity() {
        // GIVEN/WHEN: 使用默认容量创建
        let channel = LogChannel::with_default_capacity();

        // THEN: 容量应为 DEFAULT_QUEUE_SIZE
        assert_eq!(channel.capacity(), Some(DEFAULT_QUEUE_SIZE));
    }

    // UT-6.1-004: 测试 try_send 基本功能
    #[test]
    fn test_try_send_success() {
        // GIVEN: 一个空的 channel
        let channel = LogChannel::new(100);
        let event = LogEvent::new(Level::Info, "test", "message");

        // WHEN: 尝试发送
        let result = channel.try_send(event);

        // THEN: 应成功
        assert!(result.is_ok());
        assert_eq!(channel.len(), 1);
        assert!(!channel.is_empty());
    }

    // UT-6.1-005: 测试队列满时 try_send 返回错误
    #[test]
    fn test_try_send_full_queue() {
        // GIVEN: 一个容量为 2 的 channel，已填满
        let channel = LogChannel::new(2);
        let event1 = LogEvent::new(Level::Info, "test", "msg1");
        let event2 = LogEvent::new(Level::Info, "test", "msg2");
        channel.try_send(event1).unwrap_or(());
        channel.try_send(event2).unwrap_or(());

        // WHEN: 尝试发送第三条
        let event3 = LogEvent::new(Level::Info, "test", "msg3");
        let result = channel.try_send(event3);

        // THEN: 应返回 Full 错误
        assert!(result.is_err());
        assert!(channel.is_full());
    }

    // UT-6.1-006: 测试 send 基本功能
    #[test]
    fn test_send_success() {
        // GIVEN: 一个空的 channel
        let channel = LogChannel::new(100);
        let event = LogEvent::new(Level::Info, "test", "message");

        // WHEN: 发送
        let result = channel.send(event);

        // THEN: 应成功
        assert!(result.is_ok());
        assert_eq!(channel.len(), 1);
    }

    // UT-6.1-007: 测试队列状态查询方法
    #[test]
    fn test_queue_status_methods() {
        // GIVEN: 一个容量为 3 的 channel
        let channel = LogChannel::new(3);

        // THEN: 初始状态
        assert!(channel.is_empty());
        assert!(!channel.is_full());
        assert_eq!(channel.len(), 0);
        assert_eq!(channel.capacity(), Some(3));

        // WHEN: 添加一条消息
        let event = LogEvent::new(Level::Info, "test", "msg");
        channel.try_send(event).unwrap_or(());

        // THEN: 状态更新
        assert!(!channel.is_empty());
        assert!(!channel.is_full());
        assert_eq!(channel.len(), 1);

        // WHEN: 填满队列
        channel
            .try_send(LogEvent::new(Level::Info, "test", "msg2"))
            .unwrap_or(());
        channel
            .try_send(LogEvent::new(Level::Info, "test", "msg3"))
            .unwrap_or(());

        // THEN: 队列已满
        assert!(channel.is_full());
        assert_eq!(channel.len(), 3);
    }

    // UT-6.1-008: 测试 sender() 返回可用的发送端
    #[test]
    fn test_sender_clone() {
        // GIVEN: 一个 channel
        let channel = LogChannel::new(100);

        // WHEN: 获取 sender 克隆
        let sender = channel.sender();

        // THEN: sender 应可用于发送
        let event = LogEvent::new(Level::Info, "test", "via sender");
        let result = sender.try_send(event);
        assert!(result.is_ok());
        assert_eq!(channel.len(), 1);
    }

    // UT-6.1-009: 测试 receiver() 返回可用的接收端
    #[test]
    fn test_receiver_reference() {
        // GIVEN: 一个 channel 并发送消息
        let channel = LogChannel::new(100);
        let event = LogEvent::new(Level::Info, "test", "to receive");
        channel.try_send(event).unwrap_or(());

        // WHEN: 获取 receiver 并接收
        let receiver = channel.receiver();
        let received = receiver.try_recv();

        // THEN: 应成功接收
        assert!(received.is_ok());
        let received_event = received.unwrap_or_else(|_| LogEvent::new(Level::Error, "", ""));
        assert_eq!(received_event.message, "to receive");
        assert!(channel.is_empty());
    }

    // UT-6.1-010: 编译时验证 LogChannel 实现 Send + Sync
    #[test]
    fn test_logchannel_is_send_sync() {
        fn assert_send<T: Send>() {}
        fn assert_sync<T: Sync>() {}

        assert_send::<LogChannel>();
        assert_sync::<LogChannel>();
    }

    // UT-6.1-011: 测试接收端断开后 send 返回错误
    #[test]
    fn test_send_after_receiver_dropped() {
        // GIVEN: 创建 channel 并获取 sender
        let sender = {
            let channel = LogChannel::new(100);
            channel.sender()
            // channel 和 receiver 在此处被 drop
        };

        // WHEN: 尝试发送（receiver 已断开）
        let event = LogEvent::new(Level::Info, "test", "orphan");
        let result = sender.try_send(event);

        // THEN: 应返回 Disconnected 错误
        assert!(result.is_err());
    }

    // =========================================================================
    // Story 6.4: 背压策略测试
    // =========================================================================

    // UT-6.4-003: 背压计数器初始值为 0
    #[test]
    fn test_backpressure_count_initial() {
        // GIVEN/WHEN: 创建新的 channel
        let channel = LogChannel::new(100);

        // THEN: 背压计数应为 0
        assert_eq!(channel.backpressure_count(), 0);
    }

    // UT-6.4-004: 队列未满时不递增背压计数器
    #[test]
    fn test_backpressure_count_not_incremented_when_not_full() {
        // GIVEN: 一个有足够空间的 channel
        let channel = LogChannel::new(100);

        // WHEN: 发送消息（队列未满）
        let event = LogEvent::new(Level::Info, "test", "message");
        let _ = channel.send(event);

        // THEN: 背压计数应仍为 0
        assert_eq!(channel.backpressure_count(), 0);
    }

    // UT-6.4-005: 队列满时递增背压计数器 (AC-6.4.1, AC-6.4.3)
    #[test]
    fn test_backpressure_count_incremented_when_full() {
        use std::sync::Arc;
        use std::thread;
        use std::time::Duration;

        // GIVEN: 一个容量为 2 的 channel，已填满
        let channel = Arc::new(LogChannel::new(2));
        channel
            .try_send(LogEvent::new(Level::Info, "test", "msg1"))
            .unwrap_or(());
        channel
            .try_send(LogEvent::new(Level::Info, "test", "msg2"))
            .unwrap_or(());
        assert!(channel.is_full());

        // WHEN: 在另一个线程发送（会阻塞），然后消费一条消息
        let channel_clone = Arc::clone(&channel);
        let handle = thread::spawn(move || {
            let event = LogEvent::new(Level::Info, "test", "msg3");
            channel_clone.send(event)
        });

        // 等待一小段时间让发送线程阻塞
        thread::sleep(Duration::from_millis(50));

        // 消费一条消息，释放空间
        let _ = channel.receiver().try_recv();

        // 等待发送完成
        let result = handle
            .join()
            .unwrap_or(Err(Log4rError::ChannelError("join failed".into())));

        // THEN: 发送应成功，背压计数应递增
        assert!(result.is_ok());
        assert_eq!(channel.backpressure_count(), 1);
    }

    // UT-6.4-006: 多次背压递增计数器
    #[test]
    fn test_backpressure_count_multiple_increments() {
        use std::sync::Arc;
        use std::thread;
        use std::time::Duration;

        // GIVEN: 一个容量为 1 的 channel
        let channel = Arc::new(LogChannel::new(1));

        // 填满队列
        channel
            .try_send(LogEvent::new(Level::Info, "test", "msg1"))
            .unwrap_or(());

        // WHEN: 触发两次背压
        for i in 0..2 {
            let channel_clone = Arc::clone(&channel);
            let handle = thread::spawn(move || {
                let event = LogEvent::new(Level::Info, "test", format!("blocked_{}", i));
                channel_clone.send(event)
            });

            thread::sleep(Duration::from_millis(30));
            let _ = channel.receiver().try_recv(); // 释放空间
            let _ = handle.join();
        }

        // THEN: 背压计数应为 2
        assert_eq!(channel.backpressure_count(), 2);
    }

    // UT-6.4-007: 验证 BACKPRESSURE_WARNING_THRESHOLD 常量
    #[test]
    fn test_backpressure_warning_threshold_constant() {
        // GIVEN/WHEN/THEN: 常量应为 1000
        assert_eq!(super::BACKPRESSURE_WARNING_THRESHOLD, 1000);
    }
}
